home *** CD-ROM | disk | FTP | other *** search
- /*
- File: OSLEvals.c
-
- Contains:
-
- Owned by: Nick Pilch
-
- Copyright: © 1993 - 1996 by Apple Computer, Inc., all rights reserved.
-
- Change History (most recent first):
-
- <2> 1/15/96 TJ Cleaned Up
- <6> 6/22/95 NP 1261016: Don't call OSLDiposeToken when
- adding tokens to a list.
- <5> 6/20/95 NP 1252761: Restore context around a whose
- clause.
- <4> 6/13/95 eeh 1252761: whose clauses reset context
- (disabled)
- <3> 1/12/95 jpa Don't use obsolete Toolbox names [1211211]
- <2> 8/19/94 NP 1181622: Ownership fix.
- <9> 5/5/94 eeh bug #1160654: fix for SCPP
- <8> 5/2/94 eeh bug #1160654: various PPC native changes
- <7> 3/23/94 NP 1143046-unitialized local variable.
- <6> 10/18/93 NP Added mark functions callback support for
- OpenDoc.
- <5> 10/11/93 NP Removed stuff added previously for tokens.
- Changed count and compare callback
- dispatching.
- <4> 8/18/93 NP Changed MakeNullToken
- <3> 8/16/93 NP Adjusted for latest OSL proposal.
- <2> 7/28/93 NP Mods for new token type, OSLToken.
- <1> 7/21/93 NP first checked in
-
- To Do:
- */
-
- /*
- ©Apple Computer, Inc. 1992
- All Rights Reserved.
- Author: Eric House
- */
-
- #include "OSLPriv.h"
- #include <ToolUtils.h>
-
- #define UNUSED(x) ((void) &x)
-
-
- #pragma segment AEObjSuppt
-
- void
- MakeNull( AEDesc *theDesc )
- {
- theDesc->descriptorType = typeNull ;
- theDesc->dataHandle = NULL ;
- }
-
- void
- MakeNullToken( OSLToken *theToken )
- {
- theToken->descriptorType = typeNull ;
- // theToken->context = 0 ;
- theToken->dataHandle = NULL ;
- }
-
-
- static OSErr EvalTerm( Term t , DescType exmnClass, OSLToken *objBeingExamined ,
- short appDoesFlags) ;
-
-
- /*———————————————————————— EvalCompare ————————————————————————*/
-
- /*evaluates a comparison*/
-
- static OSErr
- EvalCompare( Comparison c , DescType exmnClass ,
- OSLToken *objBeingExamined , short appDoesFlags)
- {
- Boolean compResult ;
-
- OSErr err = noErr ;
- if ( (*c)->redo )
- {
- FailErr( EvalObj( (*c)->obj1, exmnClass, objBeingExamined,
- appDoesFlags ), err, errExit ) ; /* eval first object */
- FailErr( EvalObj( (*c)->obj2, exmnClass, objBeingExamined,
- appDoesFlags ), err, errExit ) ; /* eval second object */
-
- // compare em
- FailErr( NewCallCompareProc( (*c)->oper, (*((*c)->obj1))->objValue,
- (*((*c)->obj2))->objValue, &compResult ), err, errExit ) ;
- (*c)->value = compResult ;
-
- // set redo flag if either object must redo
- (*c)->redo = (*((*c)->obj1))->objRedo
- || (*((*c)->obj2))->objRedo ;
- }
-
- FAIL_ERR_PROC(err, errExit)
- if ( SetErrDesc( (*c)->theCompInput ) ) // 4/5. So doesn't dispose later */
- (*c)->theCompInput.dataHandle = NULL ;
- END_FAIL_ERR_PROC(err)
-
-
-
- } /* EvalCompare */
-
- /*———————————————————————— EvalLogical ————————————————————————*/
-
- static OSErr
- EvalLogical( Logical l , DescType exmnClass ,
- OSLToken *objBeingExamined , short appDoesFlags )
- {
- Term thisTerm ;
- Boolean thisTermVal ;
- Boolean terminateCond ;
- OSErr err = noErr;
-
- HLock((Handle)l) ;
- // WITH l** DO
- {
- LogicalPtr lp = *l ;
- if ( lp->redo )
- {
-
- if ( lp->logicalOp == kAEAND )
- terminateCond = false ;
- else if ( lp->logicalOp == kAEOR )
- terminateCond = true ;
- else if ( lp->logicalOp != kAENOT ) /* if ( not, don't care what term value is */
- FailErr( errAENoSuchLogical, err, errExit ) ;
-
- /* Grab the first term, then loop through evaluating them.
- kAENot must have exactly one term; OR and AND may have any number,
- including 0. */
-
- thisTerm = lp->firstTerm ;
- if ( (lp->logicalOp == kAENOT)
- && ((thisTerm == NULL) || ((*thisTerm)->next != NULL)) )
- FailErr( errAEWrongNumberArgs , err, errExit ) ;
-
- while( thisTerm != NULL )
- {
- FailErr( EvalTerm( thisTerm, exmnClass, objBeingExamined,
- appDoesFlags ), err, errExit ) ;
- thisTermVal = (*thisTerm)->value ;
- lp->redo |= (*thisTerm)->redo ;
-
- if ( thisTermVal == terminateCond )
- break ;
-
- thisTerm = (*thisTerm)->next ;
- } /* while */
-
- if ( lp->logicalOp == kAENOT )
- lp->value = !thisTermVal ;
- else
- lp->value = thisTermVal ; // This works for either way out of the loop */
-
- }
- }
- HUnlock((Handle)l);
-
- FAIL_ERR_PROC(err, errExit)
- if ( (l != NULL) && (SetErrDesc( (*l)->theLogicalInput )) ) /* 4/5. So doesn't dispose later */
- (*l)->theLogicalInput.dataHandle = NULL ;
- END_FAIL_ERR_PROC(err)
-
-
- } /*EvalLogical*/
-
- /*———————————————————————— EvalObj ————————————————————————*/
-
- OSErr
- EvalObj( Object o, DescType exmnClass, OSLToken *objectBeingExmn,
- short appDoesFlags )
- {
- Boolean ignoreBool ;
- OSErr err = noErr;
-
- UNUSED(appDoesFlags) ;
-
- if ( (*o)->objRedo )
- {
- HLock( (Handle)o ) ;
- // WITH o** DO
- {
- ObjRecordPtr op = *o ;
- // FailErr( iAEDisposeToken( objValue ) ) ;
- FailErr( InternalResolve( o, exmnClass,
- objectBeingExmn, &ignoreBool, &op->objValue, &op->objRedo),
- err, errExit ) ;
- }
- HUnlock((Handle)o);
- }
-
- FAIL_ERR_PROC(err, errExit)
- if ( (o != NULL) && (SetErrDesc( (*o)->theObjInput )) ) /* 4/5. So doesn't dispose later */
- (*o)->theObjInput.dataHandle = NULL ;
- END_FAIL_ERR_PROC(err)
-
- } /*EvalObj*/
-
-
- #define kKeyExmnClass ((DescType)'exmn')
-
-
-
- static OSErr
- EvalCompareEvnt( CompareEvent cevt, DescType exmnClass,
- OSLToken *objBeingExamined )
- {
- OSLToken prevExmn ;
- AESendMode sendMode = kAEWaitReply ;
- AESendPriority sendPriority = kAENormalPriority;
- AppleEvent reply ;
- DescType returnedType ;
- long actualSize ;
- Boolean trueOrFalse ;
- OSErr err = noErr ;
-
- prevExmn.dataHandle = NULL ;
- reply.dataHandle = NULL ;
-
- FailErr( GetExmn( &prevExmn ), err, errExit ) ;
- FailErr( SetExmn( objBeingExamined ), err, errExit ) ;
-
- // send the event
- HLock( (Handle) cevt ) ;
- FailErr( AEPutParamPtr( &(*cevt)->eventWParams, kKeyExmnClass, typeType,
- (Ptr)&exmnClass, sizeof(exmnClass) ), err, errExit ) ;
- FailErr( AESend( &(*cevt)->eventWParams, &reply, sendMode, sendPriority,
- kNoTimeOut, NULL, NULL ), err, errExit ) ;
- HUnlock( (Handle) cevt ) ;
-
- // get the true or false info
- FailErr( AEGetParamPtr( &reply, keyDirectObject, typeBoolean, &returnedType,
- (Ptr)&trueOrFalse, sizeof(trueOrFalse), &actualSize), err, errExit ) ;
-
- (*cevt)->value = trueOrFalse ;
-
- FailErr( SetExmn( &prevExmn ), err, errExit ) ;
-
- FAIL_ERR_PROC(err, errExit)
- if ( prevExmn.dataHandle )
- CIgnoreOSErr( SetExmn( &prevExmn ) ) ;
- if ( reply.dataHandle )
- IgnoreOSErr( AEDisposeDesc(&reply) ) ;
- END_FAIL_ERR_PROC(err)
- }
-
-
-
-
- /*———————————————————————— EvalTerm ————————————————————————*/
-
- static OSErr
- EvalTerm( Term t , DescType exmnClass, OSLToken *objBeingExamined ,
- short appDoesFlags)
- {
- // AEDesc saveDesc
-
- OSErr err = noErr;
-
- // saveDesc = objBeingExamined ; */
- HLock((Handle)t);
- if ( (*t)->redo )
- {
- switch ( (*t)->ttype )
- {
- case kCompare :
- FailErr( EvalCompare( (*t)->u.compar, exmnClass,
- objBeingExamined, appDoesFlags), err, errExit ) ;
- (*t)->redo = (*((*t)->u.compar))->redo;
- (*t)->value = (*((*t)->u.compar))->value ;
- break ;
-
- case kCompareEvt :
- FailErr( EvalCompareEvnt( (*t)->u.cEvt, exmnClass, objBeingExamined ),
- err, errExit ) ;
- (*t)->redo = (*((*t)->u.cEvt))->redo ;
- (*t)->value = (*((*t)->u.cEvt))->value ;
- break ;
-
- case kLogical :
- FailErr( EvalLogical( (*t)->u.log, exmnClass, objBeingExamined,
- appDoesFlags), err, errExit ) ;
- (*t)->redo = (*((*t)->u.log))->redo;
- (*t)->value = (*((*t)->u.log))->value ;
-
- }
-
- // if ( (*t)->value )
- // objBeingExamined = saveDesc ;
- // else
- // FailErr( iAEDisposeToken( saveDesc ) ) ;
- }
- HUnlock((Handle)t);
-
- FAIL_ERR_PROC(err, errExit)
- if ( ( t != NULL) && (SetErrDesc( (*t)->theTermInput )) ) /* 4/5. So doesn't dispose later */
- (*t)->theTermInput.dataHandle = NULL ;
- END_FAIL_ERR_PROC(err)
-
- } /*EvalTerm*/
-
-
- ////////////////////////////////////////////////////////////////////////////////////
- //
- // EvalWhose() and its service routines
- //
- ////////////////////////////////////////////////////////////////////////////////////
-
-
- // for the C port, I'm adding this struct to pass the variables that the various
- // EvalWhose service routines have access to by virtue of being nested inside
- // EvalWhose() in the Pascal version.
-
- //CONST
- //kNumDescsToAdd == 20 ; /* descriptors st||ed in a Handle: when it's full, resize by this number */
- //kStoreAllSuccesses == 0 ; /* special value f|| numToSt||e meaning infinite */
- //TYPE
- typedef AEDesc *DescArrayPtr, **DescArrayHandle ;
-
- typedef OSLToken *OSLTokenPtr, **OSLTokenHandle ;
-
- typedef struct WHG { // EvalWhoseGlobals
- OSLToken tempList ; // see EvalWhose for some comments about these
- OSLToken markToken ; // vars
- OSLTokenHandle theDescArrayH ;
- long nSuccesses ;
- long numInStorage ;
- Boolean isARange ;
- Boolean hasRelative ;
- Boolean mark ;
- Boolean goingBackward ;
- Boolean mustReturnList ;
-
- Whose w ; // this is a formal: has to be added too though
- } WHG ;
-
-
- static OSErr
- DisposeDescArray( OSLTokenPtr startDesc, long nToDispose )
- {
- OSLTokenPtr stopDesc ;
- OSErr err = noErr ;
-
- stopDesc = startDesc + nToDispose ;
- while ( startDesc < stopDesc )
- {
- FailErr( iAEDisposeToken( startDesc ), err, errExit ) ;
- ++startDesc ;
- }
-
- FAIL_ERR_PROC(err, errExit)
- END_FAIL_ERR_PROC(err)
- }
-
-
- static OSErr
- RedoListOrMark( long realStart, long realStop, WHG *wg )
- {
- long temp ;
- long sizeSought ;
- OSLTokenPtr theDescArrP ;
- OSErr err = noErr ;
-
- if ( wg->numInStorage < realStop )
- FailErr( errAENoSuchObject, err, errExit ) ; /* was errInvalidOffset */
-
- if ( realStart > realStop ) // 2/18. if we wanted the 20th && there are only 19, err||
- {
- if ( wg->isARange && wg->hasRelative
- && ((*(wg->w))->index.startCase == kAEAny)
- && ((*(wg->w))->index.stopCase == kAEAny) ) // special case for
- // any to any range
- {
- temp = realStart ;
- realStart = realStop ;
- realStop = temp ;
- }
- else if ( !(wg->mustReturnList) )
- FailErr( errAENoSuchObject, err, errExit ) ; // was errInvalidOffset
- }
-
- if ( wg->mark )
- {
- FailErr( NewCallAdjustMarks( realStart, realStop, wg->markToken ),
- err, errExit ) ;
- }
- else
- { // ok if ( realStart > realStop b/c just disposing null tokens
- HLock( (Handle)wg->theDescArrayH ) ;
- theDescArrP = *(wg->theDescArrayH) ;
-
- /* First, allow client to dispose of all the tokens we won't include in the result */
-
- if ( realStart > 1 )
- FailErr( DisposeDescArray( theDescArrP, realStart-1 ),
- err, errExit ) ;
-
- if ( wg->numInStorage > realStop )
- FailErr( DisposeDescArray( &theDescArrP[realStop] ,
- wg->numInStorage - realStop ), err, errExit ) ;
-
- /* calc the number of bytes the final array of AEDesc ought to contain */
- wg->numInStorage = realStop - realStart + 1 ;
- sizeSought = wg->numInStorage * sizeof(AEDesc) ;
-
- /* shif (t what we want to keep to the start of the block. Don't bother if ( already there.
- No need to check sizeSought>0 b/c BlockMove bails if ( negative. */
- if ( realStart > 1 )
- BlockMove( theDescArrP + realStart - 1, (Ptr)theDescArrP, sizeSought ) ;
-
- HUnlock( (Handle)wg->theDescArrayH ) ;
- SetHandleSize( (Handle)wg->theDescArrayH, sizeSought ) ;
- }
-
- FAIL_ERR_PROC(err, errExit)
- END_FAIL_ERR_PROC(err)
-
- } /* RedoListOrMark */
-
-
-
- static OSErr
- MarkOrRemember( OSLToken dToken , long index, WHG *wg )
- {
- long offset ;
- OSErr err = noErr ;
-
- if ( wg->mark )
- {
- FailErr( NewCallMark( dToken, wg->markToken, index ), err, errExit ) ;
-
- /* <eeh> The app has passed me what is most
- likely a fresh descript|| with a unique reference to a relocatable block.
- if ( I don't dispose of it before reusing the *iable the heap will fill
- up, yet this may send the wrong message to the app. I am NOT done with
- the reference to the app's object. */
- }
- else
- {
- if ( wg->goingBackward ) /* we want to st||e in reverse ||der */
- offset = 0 ;
- else
- offset = GetHandleSize( (Handle)wg->theDescArrayH ) ;
-
- Munger( (Handle)wg->theDescArrayH, offset, NULL, 0, &dToken, sizeof( dToken ) ) ;
- FailErr( MemError(), err, errExit ) ;
- }
- ++wg->numInStorage ;
-
- FAIL_ERR_PROC(err, errExit)
- END_FAIL_ERR_PROC(err)
- } /* MarkOrRemember */
-
-
-
- /*————————————*/
- static OSErr
- ResultDescriptor( OSLToken *result, WHG *wg )
- {
- long i ;
- OSLTokenPtr nextDesc ;
- OSErr err = noErr ;
-
- if ( wg->mark )
- {
- *result = wg->markToken ;
- }
-
- else
- {
- if ( (wg->numInStorage == 1) && !wg->mustReturnList )
- *result = **(wg->theDescArrayH) ;
- else
- {
- FailErr( AECreateList( NULL, 0, false, &wg->tempList ), err, errExit ) ;
-
- /* <eeh> here we put the tokens into a recognizable form -- an AEList.
- BUT NOTE: we are creating copies of the app's tokens. if ( we do not
- dispose of the descript||s after putting them in the list they will
- live in mem||y f||ever, yet to dispose is to say to the app that
- we are done with them when in fact we are not.
- So call AEDisposeDesc on them. The app can dispose of them c||rectly
- (as tokens) when it gets the resulting list back. */
-
- HLock( (Handle)wg->theDescArrayH ) ;
- nextDesc = *(wg->theDescArrayH) ;
- for( i = 1; i <= wg->numInStorage; ++i )
- {
- FailErr( AEPutDesc( &wg->tempList, i, nextDesc ), err, errExit ) ;
- IgnoreOSErr( AEDisposeDesc( nextDesc ) ) ;
- ++nextDesc ;
- }
-
- *result = wg->tempList ;
- }
-
- DisposeHandle( (Handle)wg->theDescArrayH ) ;
- }
-
- FAIL_ERR_PROC(err, errExit)
- END_FAIL_ERR_PROC(err)
- } // ResultDescriptor
-
-
-
-
- ////////////////////////////////////////////////////////////////////////////////////
- // AfterFirst()
- // determines whether a given n is >== the start of the range of
- // successes desired
- ////////////////////////////////////////////////////////////////////////////////////
- #define ABS(n) ((n)>=0?(n):-(n))
- static Boolean
- AfterFirst( long n, WHG *wg )
- {
- Boolean rval = true ;
-
- //WITH (*w)->index DO
- {
- indexRecordPtr ip = &(*(wg->w))->index ;
- if ( (ip->startCase == typeLongInteger) )
- {
- if ( wg->goingBackward )
- rval = ABS(n) >= ABS(ip->stopValue) ;
- else
- rval = ABS(n) >= ABS(ip->startValue) ;
- }
- }
- return rval ;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////////
- // BeforeLast()
- // determines whether a given n is <= the end of the range of successes
- // desired
- ////////////////////////////////////////////////////////////////////////////////////
- static Boolean
- BeforeLast( long n, WHG *wg )
- {
- Boolean rval = true ;
-
- // WITH (*w)->index DO
- {
- indexRecordPtr ip = &(*(wg->w))->index ;
- if ( (ip->stopCase == typeLongInteger) )
- {
- if ( n >= 0 ) /* we are counting up: use stop as last */
- {
- if ( ip->stopValue > 0 )
- rval = n <= ip->stopValue ;
- else
- rval = true ; /* we have to save all of them above start to do negative index */
- }
- else /* we are counting down: use start as last -- MUST be negative */
- rval = n >= ip->startValue ; /* both are negative */
- }
- }
- return rval ;
- }
-
- ////////////////////////////////////////////////////////////////////////////////////
- // ResolveSingle()
- ////////////////////////////////////////////////////////////////////////////////////
-
-
- static long
- Middle( long n )
- {
- return n+1 >> 1 ; // better than BITSHIFT and DIV 2
- }
-
- extern long MyLongMod( long l1, long l2) ;
-
- // Choose a random number from 1 to n
- static long
- JRandomNumber( long n )
- {
- long randomLong ;
- if ( n != 0 )
- {
- randomLong = ((long)Random()) << 16 ;
- randomLong |= Random() ;
- // return ABS( MyLongMod( randomLong, n ) ) + 1 ;
- randomLong %= n ;
- return (randomLong >= 0? randomLong : -randomLong ) + 1;
- }
- else
- return 0 ;
- }
-
- static OSErr
- ResolveSingle( DescType theCase, long *result, WHG *wg )
- {
- OSErr err = noErr ;
-
- if ( theCase == kAEMiddle )
- *result = Middle( wg->nSuccesses ) ;
- else if ( theCase == kAEAny )
- *result = JRandomNumber( wg->nSuccesses ) ;
- else
- FailErr( errAEImpossibleRange, err, errExit ) ;
-
- FAIL_ERR_PROC(err, errExit)
- END_FAIL_ERR_PROC(err)
- } // ResolveSingle
-
- ////////////////////////////////////////////////////////////////////////////////////
- // ResolveToInteger()
- ////////////////////////////////////////////////////////////////////////////////////
- static OSErr
- ResolveToInteger( long *realStart, long *realStop, WHG *wg )
- {
- OSErr err = noErr ;
-
- // WITH (*w)->index DO /* EvalWhose locks the whose record down */
- {
- indexRecordPtr ip = &(*(wg->w))->index ;
-
- if ( wg->hasRelative && !wg->isARange ) /* isn't going backward, && will have saved all successes;
- no longs || negative longs (UNLESS marking is in use!!!) */
- {
- if ( ip->startCase == kAEAll )
- {
- *realStart = 1 ;
- *realStop = wg->numInStorage ; /* same as wh->nSuccesses */
- }
- else if ( ip->startCase == typeLongInteger ) /* only possible if ( we're doing marking,... */
- { /* ...which will have caused us to save all successes */
- if ( ip->startValue > 0 )
- *realStart = ip->startValue ;
- else
- *realStart = wg->numInStorage + ip->startValue + 1 ;
- *realStop = *realStart ;
- }
- else
- { /* any, middle */
- long temp ;
- FailErr( ResolveSingle( ip->startCase, &temp, wg ), err, errExit ) ;
- *realStop = *realStart = temp ;
- }
- }
- else if ( wg->isARange )
- {
- if ( ip->startCase == typeLongInteger )
- {
- if ( (ip->startValue > 0) || wg->goingBackward )
- *realStart = 1 ;
- else
- *realStart = wg->numInStorage + ip->startValue + 1 ;
- }
- else
- { /* any, middle */
- long temp ;
- FailErr( ResolveSingle( ip->startCase, &temp, wg ), err, errExit ) ;
- *realStart = temp ;
- }
-
- if ( ip->stopCase == typeLongInteger )
- {
- if ( ip->stopValue >= 0 )
- {
- if ( ip->startValue >= 0 )
- *realStop = ip->stopValue - ip->startValue + 1 ;
- else
- *realStop = ip->stopValue ;
- }
- else
- {
- if ( ip->stopValue >= 0 )
- *realStop = wg->numInStorage + ip->stopValue + 1 ;
- else if ( wg->goingBackward ) // same as IF mark THEN
- *realStop = wg->numInStorage ;
- else
- *realStop = wg->numInStorage + ip->stopValue + 1; /* added 4/1 */
- }
- }
- else /* any, middle */
- {
- long temp ;
- FailErr( ResolveSingle( ip->stopCase, &temp, wg ), err, errExit ) ;
- *realStop = temp ;
- }
- }
- else /* must be a single index; positive || negative doesn't matter, as there should */
- { /* be only one in st||age anyway. if ( there aren't any in st||age, we've an */
- if ( wg->numInStorage == 1 ) /* err||. Get the 3nd n when there are only 2 ns will */
- { /* produce such a case. */
- *realStart = *realStop = 1 ;
- }
- else
- {
- // PAssert( wg->numInStorage == 0, 'wg->numInStorage != 0' ) ;
- FailErr( errAENoSuchObject, err, errExit ) ;
- }
- }
- } /*with*/
-
- FAIL_ERR_PROC(err, errExit)
- END_FAIL_ERR_PROC(err)
- } /* ResolveToInteger*/
-
-
-
-
- /*———————————————————————— EvalWhose ————————————————————————*/
- /*evaluates a Whose term*/
-
- OSErr
- EvalWhose( Whose whoz , DescType wantClass , DescType containerClass ,
- OSLToken container , short appDoesFlags )
- {
- long nElements ;
- long realStart ;
- long realStop ;
- AEDesc dIth ; /* descriptor holding selection data f|| i-th element */
- // long i ;
- OSLToken dThisElement ;
- // AEDesc tempList ; /* used where m||e than one result to be returned; dispose only on err|| */
- // AEDesc markToken ; /* change markID to descript|| 1/10; dispose only in FailErr */
- // DescArrayHandle theDescArrayH ;
- // long nSuccesses ;
- // long numInStorage ; /* used f|| marked case && unmarked: always <== nSuccesses, as excluded those cases outside of range */
- long searchStart ;
- long searchEnd ;
- long incrementer ;
- // Boolean isARange ;
- // Boolean isFromEnd ;
- // Boolean hasRelative ;
- // Boolean mark ;
- // Boolean goingBackward ;
- // Boolean mustReturnList ;
- WHG whg ;
- OSErr err = noErr;
- #define USE_TEMP_CONTEXT_CHANGE
- #ifdef USE_TEMP_CONTEXT_CHANGE
- OSLContext savedCurContext;
- #endif
-
- whg.w = whoz ;
- whg.mark = (appDoesFlags & kAEIDoMarking) != 0 ;
- MakeNullToken( &whg.markToken ) ;
- MakeNullToken( &dThisElement ) ;
- whg.nSuccesses = 0 ;
- whg.tempList.dataHandle = NULL ;
- dIth.dataHandle = NULL ;
- whg.theDescArrayH = NULL ;
-
- HLock( (Handle)whg.w ) ;
-
- // WITH whg.w** DO
- {
- WhoseRecordPtr wp = *whg.w ;
- whg.isARange = wp->index.stopCase != typeNull; // are we looking
- // for a range or one?
-
- if ( whg.isARange )
- //WITH index DO
- {
- indexRecordPtr ip = &wp->index ;
- if ( ip->stopCase == typeLongInteger )
- if ( ip->startCase == typeLongInteger )
- if ( (ip->startValue > 0) && (ip->stopValue > 0)
- && (ip->startValue > ip->stopValue)
- || ((ip->startValue < 0) && (ip->stopValue < 0)
- && (ip->startValue > ip->stopValue)) )
- FailErr( errAEImpossibleRange, err, errExit ) ;
- }
-
- FailErr( NewCallCountProc( wantClass, containerClass, container,
- &nElements ), err, errExit ) ;
-
- // This code would prevent infinite loop/crash for case where
- // CallCountProc returns negative value.
-
- if ( nElements < 0 ) /* equal to 0 may be ok: may want to return empty list rather than err|| */
- FailErr( errAENegativeCount, err, errExit ) ;
-
- if ( whg.mark )
- {
- FailErr( NewCallGetMarkToken( container, containerClass, &whg.markToken ),
- err, errExit ) ;
- }
- else
- {
- whg.theDescArrayH = (OSLTokenHandle)NewHandle( 0 ) ; /* sizeof(AEDesc) )) ;*/
- FailErr( MemError(), err, errExit ) ;
- }
- whg.numInStorage = 0 ;
-
- /* We can iterate backwards f|| advantage if (f 1) not using marking, && 2) it is either a negative index ||
- a range composed of two negative indices */
-
- whg.goingBackward = (! whg.mark)
- && (wp->index.startCase == typeLongInteger)
- && (wp->index.startValue < 0)
- && ((wp->index.stopCase == typeNull)
- || ((wp->index.stopCase == typeLongInteger)
- && (wp->index.stopValue < 0))) ;
-
- whg.mustReturnList = wp->index.startCase == kAEAll ;
-
- // hasRelative really means 'mustStoreAll'; hence it includes the case where
- // we're looking for the -2nd && would be going backwards if mark weren't
- // true
-
- whg.hasRelative = whg.mustReturnList // was (index.startCase = kAEAll)
- || ((wp->index.startCase == typeLongInteger) && (wp->index.startValue < 0)
- && ((wp->index.stopCase == typeNull)
- || ((wp->index.stopCase == typeLongInteger)
- && (wp->index.stopValue < 0)))
- && whg.mark)
- || (wp->index.startCase == kAEAny)
- || (wp->index.stopCase == kAEAny)
- || (wp->index.startCase == kAEMiddle)
- || (wp->index.stopCase == kAEMiddle) ; // tests for gross cases where
- // each and every matching element
- // must be marked or remembered
-
- // || ((index.startCase == typeLongInteger) && (index.start < 0))
- // || ((index.stopCase == typeLongInteger) && (index.stop < 0)) ;
-
- // initialize a handy ith element descriptor
- FailErr( AECreateDesc( typeLongInteger, NULL, sizeof(long), &dIth ),
- err, errExit ) ;
-
- /*
- (relatively) unoptimized whose clause evaluation: ask the app how many of a given class
- it has in the container, && loop through getting each by index && testing. F|| those
- that pass: rec||d another success, && ) check if ( we are dealing with a range ||
- relative. if ( a range we don't need to rec||d those that are before or after. if ( an
- index we know exactly which we are after && when we're done.
-
- One optimization added: if ( we are after the last n passing the test, we never keep
- track of m||e than the last n to pass the test.
- */
-
- if ( whg.goingBackward )
- {
- searchStart = nElements ;
- searchEnd = 0 ;
- incrementer = -1 ;
- }
- else
- {
- searchStart = 1 ;
- searchEnd = nElements + 1 ;
- incrementer = 1 ;
- }
-
- #ifdef USE_TEMP_CONTEXT_CHANGE
- FailErr( GetCurrentContext( &savedCurContext ), err, errExit );
- #endif
-
- while ( searchStart != searchEnd )
- {
- // Get the ith element as objBeingExamined for term
- **(long **)dIth.dataHandle = searchStart ;
- #ifdef USE_TEMP_CONTEXT_CHANGE
- // <eeh> added: start each resolution with the same context.
- SetCurrentContext(&savedCurContext);
- #endif
- FailErr( iCallAccessor( wantClass, container, containerClass,
- formAbsolutePosition, dIth, &dThisElement), err,
- errExit) ;
-
- // evaluate the term. dThisElement is exmn
- FailErr( EvalTerm( wp->theTerm, wantClass, &dThisElement, appDoesFlags ),
- err, errExit ) ;
-
- if ( (*(wp->theTerm))->value )
- {
- whg.nSuccesses += incrementer ;
-
- // since could be both a range && relative ("from the second
- // to the last"), do relative first. Range will sometimes ignore
- // cases (those not afterFirst or beforeLast) that need to be
- // considered if ( a relative is also involved.
-
- if ( whg.hasRelative )
- {
- FailErr( MarkOrRemember( dThisElement, whg.nSuccesses, &whg ),
- err, errExit ) ;
- }
- else if ( whg.isARange )
- {
- if ( AfterFirst(whg.nSuccesses, &whg) )
- {
- if ( BeforeLast( whg.nSuccesses, &whg ) )
- {
- //<eeh> this won't work for whg.nSuccesses < 0
- FailErr( MarkOrRemember( dThisElement,
- whg.nSuccesses-(wp->index.startValue-1), &whg ),
- err, errExit ) ;
- }
- else
- {
- whg.nSuccesses -= incrementer ; // 3/18; back down if ( we don't need this one
- FailErr( iAEDisposeToken( &dThisElement ),
- err, errExit ) ;// 3/23 dispose of it too!
- break ; // if ( after last, we are done with this whose
- }
- // above because can't put 2nd desc if no 1st
- }
- else
- {
- FailErr( iAEDisposeToken( &dThisElement ), err, errExit ) ;
- }
- }
- else // it's a simple index
- {
- if ( whg.nSuccesses == wp->index.startValue )
- {
- // it is the first, by definition
- FailErr( MarkOrRemember( dThisElement, 1, &whg ),
- err, errExit ) ;
- break ; // we got it; get out of for loop
- }
- else
- FailErr( iAEDisposeToken( &dThisElement ), err, errExit ) ;
- }
- }
- else
- FailErr( iAEDisposeToken( &dThisElement ), err, errExit ) ;
-
- searchStart += incrementer ;
- } // while
-
- if ( (whg.nSuccesses == 0) && !whg.mustReturnList ) // was <= 0; fixes LLD-UPG-25
- FailErr( errAENoSuchObject, err, errExit ) ; // fixes LLD-UPG-22 bug: was invalidRelative
-
- FailErr( ResolveToInteger( &realStart, &realStop, &whg ),
- err, errExit ) ;
- FailErr( RedoListOrMark( realStart, realStop, &whg ), err, errExit ) ;
-
- FailErr( ResultDescriptor( &wp->whoseValue, &whg ), err, errExit) ;
-
- IgnoreOSErr( AEDisposeDesc( &dIth ) );
-
- } // WITH
- HUnlock((Handle)whg.w);
-
-
-
-
- FAIL_ERR_PROC(err, errExit)
- long i ;
- if ( (whg.w != NULL) && (SetErrDesc( (*whg.w)->theWhoseInput )) ) /* 4/5. So doesn't dispose later */
- (*whg.w)->theWhoseInput.dataHandle = NULL ;
- IgnoreOSErr( AEDisposeDesc( &dIth ) );
- IgnoreOSErr( InternalDisposeToken( &whg.tempList ) );
- IgnoreOSErr( iAEDisposeToken( &dThisElement ) ) ;
-
- if ( whg.mark )
- IgnoreOSErr( iAEDisposeToken( &whg.markToken ) ) ;
- else if ( whg.theDescArrayH != NULL )
- {
- for( i = 0; i <= whg.numInStorage-2; ++i ) // 1 because 0-based; another because the i-1th is dThisElement, disposed above */
- {
- IgnoreOSErr( iAEDisposeToken( &(*(whg.theDescArrayH))[i] ) ) ;
- }
- DisposeHandle( (Handle)whg.theDescArrayH ) ;
- }
- END_FAIL_ERR_PROC(err)
-
-
- } // EvalWhose
-
-
-